"""用于处理聊天交互的聊天机器人 API 端点。

本模块提供聊天交互的端点，包括常规聊天、流式聊天、消息历史管理和清除聊天历史。
"""

import json
from typing import List

from fastapi import (
    APIRouter,
    Depends,
    HTTPException,
    Request,
)
from fastapi.responses import StreamingResponse
from app.core.metrics import llm_stream_duration_seconds
from app.api.v1.auth import get_current_session
from app.core.config import settings
from app.core.langgraph.graph import LangGraphAgent
from app.core.limiter import limiter
from app.core.logging import logger
from app.models.session import Session
from app.schemas.chat import (
    ChatRequest,
    ChatResponse,
    Message,
    StreamResponse,
)

# 创建API路由实例
router = APIRouter()
# 初始化LangGraph代理实例
agent = LangGraphAgent()



@router.post("/chat", response_model=ChatResponse)
# 应用速率限制装饰器，限制聊天端点的访问频率
@limiter.limit(settings.RATE_LIMIT_ENDPOINTS["chat"][0])
async def chat(
    request: Request,  # FastAPI请求对象，用于速率限制
    chat_request: ChatRequest,  # 包含用户消息的聊天请求
    session: Session = Depends(get_current_session),  # 从认证令牌获取的当前会话
):
    """使用LangGraph处理聊天请求。

    Args:
        request: 用于速率限制的FastAPI请求对象。
        chat_request: 包含消息的聊天请求。
        session: 来自认证令牌的当前会话。

    Returns:
        ChatResponse: 处理后的聊天响应。

    Raises:
        HTTPException: 处理请求时出错。
    """
    try:
        # 记录聊天请求信息，包括会话ID和消息数量
        logger.info(
            "chat_request_received",
            session_id=session.id,
            message_count=len(chat_request.messages),
        )

        # 调用代理获取响应，传入用户消息、会话ID和用户ID
        result = await agent.get_response(
            chat_request.messages, session.id, user_id=session.user_id
        )

        # 记录聊天请求处理完成
        logger.info("chat_request_processed", session_id=session.id)

        # 返回处理结果
        return ChatResponse(messages=result)
    except Exception as e:
        # 记录错误日志，包括会话ID和错误详情
        logger.error("chat_request_failed", session_id=session.id, error=str(e), exc_info=True)
        # 抛出HTTP异常，返回500错误
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/chat/stream")
# 应用速率限制装饰器，限制流式聊天端点的访问频率
@limiter.limit(settings.RATE_LIMIT_ENDPOINTS["chat_stream"][0])
async def chat_stream(
    request: Request,  # FastAPI请求对象，用于速率限制
    chat_request: ChatRequest,  # 包含用户消息的聊天请求
    session: Session = Depends(get_current_session),  # 从认证令牌获取的当前会话
):
    """使用LangGraph处理聊天请求并返回流式响应。

    Args:
        request: 用于速率限制的FastAPI请求对象。
        chat_request: 包含消息的聊天请求。
        session: 来自认证令牌的当前会话。

    Returns:
        StreamingResponse: 聊天完成的流式响应。

    Raises:
        HTTPException: 处理请求时出错。
    """
    try:
        # 记录流式聊天请求信息，包括会话ID和消息数量
        logger.info(
            "stream_chat_request_received",
            session_id=session.id,
            message_count=len(chat_request.messages),
        )

        # 定义事件生成器函数，用于生成流式响应
        async def event_generator():
            """生成流式事件。

            Yields:
                str: JSON格式的服务器发送事件。

            Raises:
                Exception: 流式传输过程中出错。
            """
            try:
                # 初始化完整响应字符串
                full_response = ""
                # 记录流式响应持续时间的指标
                with llm_stream_duration_seconds.labels(model=agent.llm.model_name).time():
                    # 异步迭代代理返回的流式响应块
                    async for chunk in agent.get_stream_response(
                        chat_request.messages, session.id, user_id=session.user_id
                     ):
                        # 累加响应块到完整响应中
                        full_response += chunk
                        # 创建流式响应对象，标记为未完成
                        response = StreamResponse(content=chunk, done=False)
                        # 以SSE格式发送响应块
                        yield f"data: {json.dumps(response.model_dump())}\n\n"

                # 发送完成消息
                final_response = StreamResponse(content="", done=True)
                yield f"data: {json.dumps(final_response.model_dump())}\n\n"

            except Exception as e:
                # 记录流式传输错误日志
                logger.error(
                    "stream_chat_request_failed",
                    session_id=session.id,
                    error=str(e),
                    exc_info=True,
                )
                # 创建错误响应对象
                error_response = StreamResponse(content=str(e), done=True)
                # 以SSE格式发送错误信息
                yield f"data: {json.dumps(error_response.model_dump())}\n\n"

        # 返回流式响应，设置媒体类型为SSE
        return StreamingResponse(event_generator(), media_type="text/event-stream")

    except Exception as e:
        # 记录流式聊天请求错误日志
        logger.error(
            "stream_chat_request_failed",
            session_id=session.id,
            error=str(e),
            exc_info=True,
        )
        # 抛出HTTP异常，返回500错误
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/messages", response_model=ChatResponse)
# 应用速率限制装饰器，限制消息获取端点的访问频率
@limiter.limit(settings.RATE_LIMIT_ENDPOINTS["messages"][0])
async def get_session_messages(
    request: Request,  # FastAPI请求对象，用于速率限制
    session: Session = Depends(get_current_session),  # 从认证令牌获取的当前会话
):
    """获取会话的所有消息。

    Args:
        request: 用于速率限制的FastAPI请求对象。
        session: 来自认证令牌的当前会话。

    Returns:
        ChatResponse: 会话中的所有消息。

    Raises:
        HTTPException: 检索消息时出错。
    """
    try:
        # 从代理获取聊天历史记录
        messages = await agent.get_chat_history(session.id)
        # 返回聊天历史记录
        return ChatResponse(messages=messages)
    except Exception as e:
        # 记录获取消息失败的错误日志
        logger.error("get_messages_failed", session_id=session.id, error=str(e), exc_info=True)
        # 抛出HTTP异常，返回500错误
        raise HTTPException(status_code=500, detail=str(e))


@router.delete("/messages")
# 应用速率限制装饰器，限制清除聊天历史端点的访问频率
@limiter.limit(settings.RATE_LIMIT_ENDPOINTS["messages"][0])
async def clear_chat_history(
    request: Request,  # FastAPI请求对象，用于速率限制
    session: Session = Depends(get_current_session),  # 从认证令牌获取的当前会话
):
    """清除会话的所有消息。

    Args:
        request: 用于速率限制的FastAPI请求对象。
        session: 来自认证令牌的当前会话。

    Returns:
        dict: 表示聊天历史已清除的消息。
    """
    try:
        # 调用代理清除聊天历史记录
        await agent.clear_chat_history(session.id)
        # 返回成功消息
        return {"message": "聊天历史已成功清除"}
    except Exception as e:
        # 记录清除聊天历史失败的错误日志
        logger.error("clear_chat_history_failed", session_id=session.id, error=str(e), exc_info=True)
        # 抛出HTTP异常，返回500错误
        raise HTTPException(status_code=500, detail=str(e))